//
//  ViewController.swift
//  闭包的循环引用
//
//  Created by Summer on 2017/11/14.
//  Copyright © 2017年 Summer. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    // 属性都是强引用，self强引用finishedCallBack这个闭包
    var finishedCallBack: ((_ msg:String)->())?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // 造成循环引用
        // loadData这个闭包引用self.view，
        
        // 写法1
//        // [weak self]表示这个block中不对self进行强引用，self是可以随时被释放
        // weak的特点
        // 1.不会强引用
        // 2.指向地址的对象一旦释放了，弱引用的地址会自动设置为nil
//        loadData {[weak self] (msg) in
//            // 闭包是准备好的代码，必须使用self.
//            print(msg + "\(self?.view)")
//        }
        
        // 写法2
        // unowned 会记录self的地址，不对self进行强引用，地址始终存在，所以不需要解包操作
        // 风险：一旦self真的被释放了，就会崩溃
        // 特点：对象被释放，地址不改变，即会野指针访问
        // 本质上是assign
        loadData {[unowned self] (msg) in
            // 闭包是准备好的代码，必须使用self.
            print(msg + "\(self.view)")
        }
        
        
    }

    // OC的方式解决
    func demoOC() {
        
        // OC解决循环引用的方式
        // __weak typeof(self) weakSelf = self
        // 特点：如果self已经被释放，则为nil
        
        // __unsafe _unretained   iOS4使用，MRC的写法
        // __unsafe _unretained 内存地址就是一个整数，这个整数一旦被释放，不做任何操作，本质上是assign，不会做强引用
        // __unsafe _unretained typeof(self) weakSelf
        // 特点：如果self已经被释放，则出现野指针访问
        
        
        
        
        
        weak var weakSelf = self
        
        loadData { (msg) in
            // 闭包是准备好的代码，必须使用self.
            print(msg + "\(weakSelf?.view)")
        }
    }
    
    
    
    
    
    
    // 闭包的使用
    // 1.参数传递
    // 2.使用属性记录，在需要的时候执行
    func loadData(finished: @escaping (_ msg:String)->()) {

        DispatchQueue.global().async {
            // code
            print("耗时操作")
            DispatchQueue.main.async {
                // 主线程中
//                finished("Hello")
                
                // 使用属性记录
                self.finishedCallBack = finished
                self.working()
            }
        }
    }
    
    func working() {
        // 执行闭包
        // !表示闭包一定存在，就执行，不存在则崩溃
//        finishedCallBack!("hello")
        // ?表示闭包若不存在，则返回，不执行
        finishedCallBack?("hello")
    }

    deinit {
        print("释放了")
    }

}

